﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phuse.Net.Forums
{
    using System;
    using System.Data.Linq;
    using System.Data.Linq.Mapping;
    using System.Diagnostics.CodeAnalysis;
    using Microsoft.Phone.Data.Linq.Mapping;

    /// <content>Contains the LINQ to SQL portion of the <see cref="OutboundArticle"/> class.</content>
    [Table]
    [Index(Columns = "HostId,IsDeleted,SendStatus,DateUtc")]
    [Index(Columns = "IsDeleted,SendStatus,DateUtc DESC")]
    [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "The order of the properties defines the order of database columns.")]
    internal sealed partial class OutboundArticle
    {
        private EntityRef<Host> hostRef;
        private bool isDeleted;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        [Column(IsPrimaryKey = true, IsDbGenerated = true)]
        private int Id { get; set; }

        [Column(UpdateCheck = UpdateCheck.Never)]
        private int HostId { get; set; }

        /// <summary>See <see cref="IOutboundArticle.DateUtc"/>.</summary>
        [Column(UpdateCheck = UpdateCheck.Never)]
        public DateTime? DateUtc { get; internal set; }

        /// <summary>See <see cref="IOutboundArticle.Subject"/>.</summary>
        [Column(DbType = "NVARCHAR(128)", UpdateCheck = UpdateCheck.Never)]
        public string Subject { get; internal set; }

        /// <summary>See <see cref="IOutboundArticle.SendStatus"/>.</summary>
        [Column(UpdateCheck = UpdateCheck.Never)]
        internal SendStatus SendStatus { get; set; }

        /// <summary>See <see cref="IOutboundArticle.IsDeleted"/>.</summary>
        [Column(Storage = "isDeleted", UpdateCheck = UpdateCheck.Never)]
        public bool IsDeleted
        {
            get
            {
                return this.isDeleted;
            }

            set
            {
                this.AssertValid();
                this.isDeleted = value;
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>See <see cref="IOutboundArticle.SendStatus"/>.</summary>
        SendStatus IOutboundArticle.SendStatus
        {
            get
            {
                return this.SendStatus;
            }

            set
            {
                this.AssertValid();

                if (value == SendStatus.Sent)
                {
                    throw new ArgumentException("Must not be set to SendStatus.Sent");
                }

                if (this.SendStatus == SendStatus.Sent)
                {
                    throw new InvalidOperationException("Must not be modified once sent.");
                }

                this.SendStatus = value;
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        [Association(Name = "Host_OutboundArticle", Storage = "hostRef", ThisKey = "HostId", IsForeignKey = true)]
        internal Host Host
        {
            get { return this.hostRef.Entity; }
            set { this.hostRef.Entity = value; }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void AssertValid()
        {
            this.Root.AssertValid();
        }

        private void OnValidate(ChangeAction action)
        {
            if (action == ChangeAction.Update)
            {
                var root = this.Root;
                var original = root.GetOriginalEntityState(this);

                if ((original.IsDeleted != this.IsDeleted) || (original.SendStatus != this.SendStatus))
                {
                    root.AssertSendReceiveNotInProgress();
                }
            }

            if ((action == ChangeAction.Insert) || (action == ChangeAction.Update))
            {
                this.DateUtc = ValidationHelper.LimitToSqlDateTime(this.DateUtc);
            }
        }
    }
}
